import { PropType, computed, defineComponent, ref } from 'vue';
import formFieldRef from '../../use/formFieldRef';
import { FeatherEye, FeatherEyeOff, FeatherSearch, FeatherXCircle } from 'cui-vue-icons/feather';
import WordCount from '../../WordCount';

export interface InputProps {
    name?: string
    disabled?: boolean
    size?: 'small'|'default'|'large'
    type?: string
    append?: any
    prepend?: any
    prefix?: any
    suffix?: any
    suffixStyle?: any
    prefixStyle?: any
    clearable?: boolean
    placeholder?: string
    autocomplete?: string
    trigger?: string
    modelValue?: string | number
    password?: boolean
    wordCount?: boolean
    maxLength?: number
    autoHeight?: boolean
    asFormField?: boolean
    rows?: number
    enterButton?: boolean
}

export default defineComponent({
    name: 'CInput',
    props: {
        name: {
            type: String,
        },
        disabled: {
            type: Boolean,
        },
        size: {
            type: String as PropType<InputProps['size']>,
        },
        type: {
            type: String,
        },
        append: {
            type: [String, Object],
        },
        prepend: {
            type: [String, Object],
        },
        prefix: {
            type: [String, Object],
        },
        suffix: {
            type: [String, Object],
        },
        suffixStyle: {
            type: Object,
        },
        prefixStyle: {
            type: Object,
        },
        clearable: {
            type: Boolean,
        },
        placeholder: {
            type: String,
        },
        autocomplete: {
            type: String,
        },
        trigger: {
            type: String,
        },
        modelValue: {
            type: [String, Number],
        },
        password: {
            type: Boolean,
        },
        wordCount: {
            type: Boolean,
        },
        maxLength: {
            type: Number,
        },
        autoHeight: {
            type: Boolean,
        },
        asFormField: {
            type: Boolean,
            default: true
        },
        rows: {
            type: Number,
        },
        enterButton: {
            type: Boolean,
        },
    },
    emits: ['update:modelValue', 'input', 'search', 'change', 'clear', 'focus', 'blur', 'compositionstart', 'compositionend', 'enter', 'keyUp', 'keyDown'],
    setup (props, {emit, expose}) {
        const type = ref(props.type || 'text');
        const suffix = computed(() => {
            if (props.password) {
                return type.value === 'password' ? <FeatherEyeOff class="cm-input-password-icon" onClick={togglePassword}/>
                    : <FeatherEye class="cm-input-password-icon" onClick={togglePassword}/>;
            }
            if (type.value === 'search' && !props.enterButton) {
                return <FeatherSearch style={{cursor: 'pointer'}} onClick={onSearch}/>;
            }
            return props.suffix;
        });

        const togglePassword = () => {
            type.value = type.value === 'password' ? 'text' : 'password';
        };
        // emit search
        const onSearch = () => {
            if (type.value === 'search') {
                emit('search', _value.value);
            }
        };
        const append = computed(() => {
            if (props.enterButton) {
                return typeof props.enterButton === 'string' ? props.enterButton : <FeatherSearch onClick={onSearch}/>;
            }
            return props.append;
        });

        const clazzName = computed(() => ({
            'cm-input-wrapper': true,
            'cm-input-disabled': props.disabled,
            'cm-input-auto-height': props.autoHeight,
            'cm-textarea': type.value === 'textarea',
            'cm-search-input': type.value === 'search',
            'cm-input-hidden': type.value === 'hidden',
            [`cm-input-${props.size}`]: props.size,
            'cm-input-group-with-prefix': props.prefix,
            'cm-input-group-with-suffix': suffix.value,
            'cm-input-group-with-append': append.value,
            'cm-input-group-with-prepend': props.prepend
        }));
        const input = ref();

        const inputStyle: any = {};
        if (props.suffixStyle && props.suffixStyle.width) {
            inputStyle['padding-right'] = props.suffixStyle.width + 'px';
        }
        if (props.prefixStyle && props.prefixStyle.width) {
            inputStyle['padding-left'] = props.prefixStyle.width + 'px';
        }
        const _value = formFieldRef(props, emit);
        const trigger = props.trigger || 'blur';
        const valForCount = ref<any>(_value.value);
        const isCompositioning = ref(false);

        const _onInput = (e: any) => {
            if (trigger === 'input') {
                // 输入中文时，不触发change
                if (!isCompositioning.value) {
                    _value.value = e.target.value;
                    emit('change', e.target.value);
                }
            }
            emit('input', e.target.value, e);
            valForCount.value = e.target.value;
            type.value === 'textarea' && props.autoHeight && _autoHeight(e);
        };

        const _onCompositionStart = (e: any) => {
            isCompositioning.value = true;
            emit('compositionstart', e);
        };

        const _onCompositionEnd = (e: any) => {
            isCompositioning.value = false;
            _onInput(e);
            emit('compositionend', e);
        };

        let initHeight: number;
        const _autoHeight = (event: any) => {
            const ele = event.target;
            if (!initHeight) {
                initHeight = ele.clientHeight;
            }
            if (ele.scrollHeight > initHeight) {
                if (ele.value.split('\n').length === 1) {
                    ele.style.height = `${initHeight}px`;
                } else {
                    ele.style.height = 'auto';
                }
                ele.style.overflowY = 'hidden';
                ele.scrollTop = 0; // 防抖动
                ele.style.height = `${ele.scrollHeight}px`;
            }
        };

        const _onChange = (e: any) => {
            // setValue(e.target.value);
        };

        const onBlurChange = (e: any) => {
            const v = e.target.value;
            _value.value = v;
            if (trigger === 'blur') {
                emit('change', e.target.value);
            }
            emit('blur', e);
        };

        const clear = () => {
            _value.value = '';
            emit('change', '');
        };

        const _onKeyUp = (e: any) => {
            if (e.keyCode === 13) {
                emit('enter', _value.value);
                if (type.value === 'search') {
                    onSearch();
                }
            }
            emit('keyUp', e);
        };

        const _onKeyDown = (e: any) => {
            if (e.keyCode === 13) {
                _value.value = e.target.value;
                emit('change', e.target.value);
            }
            emit('keyDown', e);
        };

        expose({
            getInput: () => input.value
        });

        // onMounted(() => {
        //     console.log(input.value);

        //     input.value.addEventListener('compositionstart', _onCompositionStart, false);
        //     input.value.addEventListener('compositionend', _onCompositionEnd, false);
        // });

        return () => <div class={clazzName.value}>
            {
                props.prefix ? <div class="cm-input-prefix" style={props.prefixStyle}>{props.prefix}</div> : null
            }
            {
                props.prepend ? <div class="cm-input-group-prepend">{props.prepend}</div> : null
            }
            {
                type.value === 'textarea'
                    ? <textarea class="cm-input" ref={input} value={_value.value} spellcheck={false} autocomplete={props.autocomplete || 'off'} wrap="soft"
                        onChange={_onChange} onInput={_onInput} onBlur={onBlurChange} disabled={props.disabled}
                        style={inputStyle} onKeyDown={_onKeyDown} onKeyUp={_onKeyUp} />
                    :<input class="cm-input" value={_value.value} placeholder={props.placeholder} name={props.name} autocomplete={props.autocomplete || 'off'}
                        onChange={_onChange} onInput={_onInput} onBlur={onBlurChange} disabled={props.disabled} ref={input}
                        style={inputStyle} onKeydown={_onKeyDown} onKeyup={_onKeyUp} type={type.value} onCompositionstart={_onCompositionStart} onCompositionend={_onCompositionEnd}/>
            }
            {
                props.clearable && _value.value ? <FeatherXCircle class="cm-input-clear" onClick={clear}/> : null
            }
            {
                suffix.value || (props.wordCount && props.maxLength)
                    ? <div class="cm-input-suffix" style={props.suffixStyle}>
                        {
                            props.wordCount && props.maxLength
                                ? <WordCount total={props.maxLength!} value={valForCount.value}/>
                                : suffix.value
                        }
                    </div>
                    : null
            }
            {
                append.value ? <div class={`cm-input-group-append`}>{append.value}</div> : null
            }
        </div>;
    }
});
